package simple_riscv
import spinal.core.fiber.{Handle, Lock}
import spinal.core._
import scala.reflect.{classTag, ClassTag}

class Framework(plugins: Seq[Plugin]) extends Component{
    val configLock, earlyBuildLock, lateBuildLock = Lock()
    configLock.retain()
    earlyBuildLock.retain()
    lateBuildLock.retain()

    plugins.foreach(_.frame.load(this)) 
    configLock.release() // dispatch all config thread
    
    plugins.foreach(_.configHandleArr.foreach(_.await())) // wait all config thread over
 
    earlyBuildLock.release() // dispatch all early 
    val lateUnlock = Handle{
        lateBuildLock.release()
    }

    def getServiceOf[T <: Service : ClassTag]() = {
        val classzz = classTag[T].runtimeClass
        plugins.filter(o => classzz.isAssignableFrom(o.getClass()))
    }

    def getService[T <: Service : ClassTag](): T = {
        val arr = getServiceOf[T]()
        arr.length match {
            case 0 => throw new Exception(s"Can't find the service ${classTag[T].runtimeClass.getName}")
            case 1 => arr.head.asInstanceOf[T]
            case _ => throw new Exception(s"Found multiple instances of ${classTag[T].runtimeClass.getName}")
        }
    }
}
